﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Linq.Expressions;
using Feedback.DataAccess;
using Feedback.Global;


namespace Feedback.Business
{
    public class FeedbackLogic
    {
        public bool Save(double? longitude, double? latitude, string locationName, string address, string feedbackText, string customerEmail, string mobileId, string googleMapsId, int? businessIdentId, string hash)
        {
            using (var context = new FeedbackContextEx())
            {
                var busineddIdent = context.BusinessIdentifications.FirstOrDefault(bi => bi.Id == businessIdentId);
                if (busineddIdent != null)
                {
                    SaveFeedback(context, busineddIdent, feedbackText, customerEmail, mobileId);
                }
                else
                {
                    var sender = new Sender
                                     {
                                         IsByMail = false,
                                         IsBySms = false,
                                         IsByApp = false,
                                         GoogleMapsId = googleMapsId,
                                         BusinessIdentificationId = businessIdentId,
                                         StoreName = locationName,
                                         Latitude = latitude,
                                         Longitude = longitude,
                                         MobileId = mobileId,
                                         LastUpdated = DateTime.Now
                                     };
                    context.Senders.AddObject(sender);
                    context.SaveChanges();
                }
            }
            return true;
        }

        private void SaveFeedback(FeedbackContextEx context, BusinessIdentification busineddIdent, string feedbackText, string customerEmail, string mobileId)
        {
            var feedback = new DataAccess.Feedback();
            context.Feedbacks.AddObject(feedback);
            feedback.ReceivedDate = DateTime.Now;
            feedback.Message = feedbackText;
            feedback.BusinessIdentificationId = busineddIdent.Id;
            feedback.LastUpdated = DateTime.Now;
            var customer =
                context.Customers.FirstOrDefault(c => c.Email == customerEmail || c.MobileId == mobileId);
            if (customer != null)
            {
                feedback.CustomerId = customer.Id;
            }
            else
            {
                customer = new Customer
                               {
                                   Email = customerEmail,
                                   MobileId = mobileId,
                                   LastUpdated = DateTime.Now
                               };
                feedback.Customer = customer;
            }
            context.SaveChanges();
        }

        public List<DataAccess.Feedback> GetAll(int businessId)
        {
            using (var context = new FeedbackContextEx())
            {
                List<int> busIdenList =
                    context.BusinessIdentifications.Where(b => b.BusinessId == businessId).Select(b => b.Id).ToList();
                var feedbackList =
                    context.Feedbacks.Include("MergeFeedbacks").Where(f =>
                                                                      busIdenList.Contains(f.BusinessIdentificationId) &&
                                                                      (f.IsDeleted == null || !f.IsDeleted.Value) &&
                                                                      (f.isMerged == null || !f.isMerged.Value) &&
                                                                      (f.Customer.IsBlackListed == null ||!f.Customer.IsBlackListed.Value)).ToList();
                
                
                foreach (var feedback in feedbackList)
                {
                    if (feedback.MergeFeedbacks.Count > 0)
                    {
                        List<int> idList = feedback.MergeFeedbacks.Select(mf => mf.MergeFeedbackId).ToList();
                        feedback.MergeFeedbackList = context.Feedbacks.Where(f => idList.Contains(f.Id)).ToList();
                    }

                }
                return feedbackList;
            }
        }
        public List<DataAccess.Feedback> GetAll(string sortBy, int businessId)
        {
            using (var context = new FeedbackContextEx())
            {
                List<int> busIdenList =
                       context.BusinessIdentifications.Where(b => b.BusinessId == businessId).Select(b => b.Id).ToList();

                var feebacks =
                    context.Feedbacks.Include("MergeFeedbacks").Where(f => (busIdenList.Contains(f.BusinessIdentificationId) &&
                        f.IsDeleted == null || !f.IsDeleted.Value) &&
                        (f.isMerged == null || !f.isMerged.Value) &&
                        (f.Customer.IsBlackListed == null || !f.Customer.IsBlackListed.Value));
                Func<DataAccess.Feedback, bool> sortExpression = null;
                switch (sortBy)
                {
                    case WellKnownNames.PositiveFeedback:
                        sortExpression = f => f.IsPositive == true;
                        break;
                    case WellKnownNames.NegativeFeedback:
                        sortExpression = f => f.IsNegative == true;
                        break;
                    case WellKnownNames.StarredFeedback:
                        sortExpression = f => f.IsStarred == true;
                        break;
                    case WellKnownNames.FeedbackFromToday:
                        DateTime now = DateTime.Now;
                        DateTime startDate = new DateTime(now.Year, now.Month, now.Day, 0, 0, 0);
                        DateTime endDate = new DateTime(now.Year, now.Month, now.Day, 23, 59, 59);
                        sortExpression = f => f.ReceivedDate >= startDate && f.ReceivedDate <= endDate;
                        break;
                    case WellKnownNames.FeedbackFromLastWeek:
                        now = DateTime.Now;
                        startDate = new DateTime(now.Year, now.Month, (now.Day - 7), 0, 0, 0);
                        endDate = new DateTime(now.Year, now.Month, now.Day, 23, 59, 59);
                        sortExpression = f => f.ReceivedDate >= startDate && f.ReceivedDate <= endDate;
                        break;

                }
                var feedbackList = feebacks.Where(sortExpression).ToList();
                foreach (var feedback in feedbackList)
                {
                    if (feedback.MergeFeedbacks.Count > 0)
                    {
                        List<int> idList = feedback.MergeFeedbacks.Select(mf => mf.MergeFeedbackId).ToList();
                        feedback.MergeFeedbackList = context.Feedbacks.Where(f => idList.Contains(f.Id)).ToList();
                    }

                }
                return feedbackList;
            }
        }

        public bool UpdatePositiveFeedbacks(List<int> selectedIdList)
        {
            using (var context = new FeedbackContextEx())
            {
                foreach (var id in selectedIdList)
                {
                    var feedback = context.Feedbacks.FirstOrDefault(f => f.Id == id);
                    if (feedback != null)
                    {
                        feedback.IsPositive = true;
                    }
                }
                context.SaveChanges();
            }
            return true;
        }
        public bool UpdateNegativeFeedbacks(List<int> selectedIdList)
        {
            using (var context = new FeedbackContextEx())
            {
                foreach (var id in selectedIdList)
                {
                    var feedback = context.Feedbacks.FirstOrDefault(f => f.Id == id);
                    if (feedback != null)
                    {
                        feedback.IsNegative = true;
                    }
                }
                context.SaveChanges();
            }
            return true;
        }

        public bool DeleteFeedbacks(List<int> selectedIdList)
        {
            using (var context = new FeedbackContextEx())
            {
                foreach (var id in selectedIdList)
                {
                    var feedback = context.Feedbacks.FirstOrDefault(f => f.Id == id);
                    if (feedback != null)
                    {
                        feedback.IsDeleted = true;
                    }
                }
                context.SaveChanges();
            }
            return true;
        }

        public bool BlockFeedbacks(List<int> selectedIdList)
        {
            using (var context = new FeedbackContextEx())
            {
                foreach (var id in selectedIdList)
                {
                    var cust = context.Customers.FirstOrDefault(c => c.Feedbacks.Any(f => f.Id == id));
                    if (cust != null)
                        cust.IsBlackListed = true;
                }
                context.SaveChanges();
            }
            return true;
        }

        public bool MergeFeedback(string ownerId, string mergeId)
        {
            int fownerId;
            if (!int.TryParse(ownerId, out fownerId))
                return false;
            var mergeIds = mergeId.Split('|');
            using (var context = new FeedbackContextEx())
            {
                foreach (var id in mergeIds)
                {
                    if(string.IsNullOrWhiteSpace(id))continue;
                    var mergeFeedback = new MergeFeedback();
                    mergeFeedback.FeedbackId = fownerId;
                    mergeFeedback.MergeFeedbackId = Convert.ToInt32(id);
                    mergeFeedback.LastUpdated = DateTime.Now;
                    context.MergeFeedbacks.AddObject(mergeFeedback);
                    var feedback = context.Feedbacks.First(f => f.Id == mergeFeedback.MergeFeedbackId);
                    feedback.isMerged = true;
                }
                context.SaveChanges();
            }
            return true;
        }
    }
}
